package edu.polsl.bio.str.node.logic;

import edu.polsl.bio.str.common.util.SystemUtils;
import edu.polsl.bio.str.node.utils.WebContextInitializationFinishedEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;

import javax.annotation.PostConstruct;
import java.net.UnknownHostException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * //todo class description
 * <p/>
 * Created on: Jun 11, 2011 11:41:22 PM <br/>
 * <a href="http://www.polsl.pl">www.polsl.pl</a>
 *
 * @author lukasz.olczak@polsl.pl
 */
public class LifecycleBean implements ApplicationListener {
  /**
   * slf4j Logger.
   */
  private static final Logger log = LoggerFactory.getLogger(LifecycleBean.class.getName());

  private static final long KEEP_ALIVE_TIME = 100;

  private ExecutorService executor;

  private NodeContext nodeContext;

  private int numOfCpu;

  private NodeControlBean nodeControlBean;

  private ConnectionLossHandler connectionLossHandler;

  @PostConstruct
  public void init() {
    log.info("Starting initialization of node");
    numOfCpu = Runtime.getRuntime().availableProcessors();
    nodeContext.setNumberOfCpu(numOfCpu);
    nodeContext.setNumberOfActiveJobs(0);
    log.info("Found {} CPUs", numOfCpu);
    createMessageConsumers(numOfCpu);
    detectNodeIp();
  }

  private void detectNodeIp() {
    try {
      String nodeIp = SystemUtils.getNonLoopbackAddress();
      log.info("Node ip address: {}", nodeIp);
      nodeContext.setNodeIp(nodeIp);
    } catch (UnknownHostException e) {
      log.error("Can't determine ip address", e);
    }
  }

  @Override
  public void onApplicationEvent(ApplicationEvent event) {
    log.debug("{} published", event);//todo remove it
    /*
    org.springframework.context.event.ContextClosedEvent
    lub shutdown hook tak jak activemq
     */
    if (event instanceof WebContextInitializationFinishedEvent) {
      log.debug("Web context initialization finished");
      try {
        nodeControlBean.attachNode(nodeContext.getManagerIp(), nodeContext.getNodeIp());
      } catch (Exception e) {
        log.error("Exception occurred during attaching", e);
        connectionLossHandler.handleConnectionLoss();
      }
    }
  }

  private void createMessageConsumers(int numOfCpu) {
    executor = new ThreadPoolExecutor(numOfCpu, numOfCpu, KEEP_ALIVE_TIME, TimeUnit.HOURS, new LinkedBlockingQueue<Runnable>());

  }

  public ExecutorService getExecutor() {
    return executor;
  }

  public void setNodeControlBean(NodeControlBean nodeControlBean) {
    this.nodeControlBean = nodeControlBean;
  }

  public void setNodeContext(NodeContext nodeContext) {
    this.nodeContext = nodeContext;
  }

  public void setConnectionLossHandler(ConnectionLossHandler connectionLossHandler) {
    this.connectionLossHandler = connectionLossHandler;
  }
}
